package com.settlement.system.controller;

import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson2.JSONObject;
import com.settlement.system.common.constant.KafkaConstants;
import com.settlement.system.common.constant.SystemConstants;
import com.settlement.system.common.result.Result;
import com.settlement.system.common.util.DateUtils;
import com.settlement.system.common.util.EasyExcelImportUtils;
import com.settlement.system.common.util.StringUtils;
import com.settlement.system.handler.disruptor.MessageVo;
import com.settlement.system.model.entity.KafkaSendErrorRecord;
import com.settlement.system.model.entity.SysBaseColumnMatch;
import com.settlement.system.model.entity.SysStore;
import com.settlement.system.model.vo.OriginalOmsOrderImportVo;
import com.settlement.system.model.vo.OriginalOmsReturnOrderImportVo;
import com.settlement.system.service.KafkaSendErrorRecordService;
import com.settlement.system.service.SnowflakeIdWorker;
import com.settlement.system.service.SysBaseColumnMatchService;
import com.settlement.system.service.SysStoreService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.SendResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * <p>
 * OMS订单 前端控制器
 * </p>
 */
@RestController
@RequestMapping("/api/v1/omsOrder")
@RequiredArgsConstructor
public class OMSController {

    private final Logger logger = LoggerFactory.getLogger(OMSController.class);

    private final SysStoreService sysStoreService;

    private final SysBaseColumnMatchService sysBaseColumnMatchService;

    private final KafkaTemplate<String, String> kafkaTemplate;

    private final KafkaSendErrorRecordService kafkaSendErrorRecordService;
    private final SnowflakeIdWorker snowflakeIdWorker = SnowflakeIdWorker.getInstance();

    /**
     * 接口推送OMS订单或者售后单
     *
     * @param dataList OMS订单或者售后单的数据结构 里面必须有一个字段来区分是OMS订单还是售后单（暂定 omsOrder 0 是OMS订单 1 是售后单）
     * @return Result 返回结果
     */
    @Operation(summary = "接口推送OMS订单或者售后单")
    @PostMapping("/data/{omsReturnOrder}")
    public Result<?> orderPush(@RequestBody List<Map<String, String>> dataList, @Parameter(description = "是否是OMS售后单") @PathVariable Integer omsReturnOrder) {
        boolean isOmsReturnOrder = omsReturnOrder == 1;
        for (Map<String, String> dataMap : dataList) {
            logger.info("接口推送OMS订单：%s".formatted(JSONObject.toJSONString(dataMap)));
            String innerSystemStoreCode = dataMap.get("storeId");
            SysStore sysStore = sysStoreService.getByInnerSystemStoreCode(innerSystemStoreCode);
            if (Objects.isNull(sysStore)) {
                logger.info("内部系统店铺编码【%s】不存在".formatted(innerSystemStoreCode));
                continue;
            }
            MessageVo vo = new MessageVo();
            // 是否是OMS订单
            vo.setOmsOrder(true);
            vo.setStoreId(sysStore.getId());
            // 是否是OMS售后单
            vo.setOmsReturnOrder(isOmsReturnOrder);
            vo.setDataMap(dataMap);
            vo.setUuid(snowflakeIdWorker.nextId());
            // 推送到转换标准订单的消息队列
            CompletableFuture<SendResult<String, String>> completableFuture = kafkaTemplate.send(KafkaConstants.HWG_TOPIC_ORDER_QUEUE, JSONObject.toJSONString(vo));
            completableFuture.whenComplete((result, throwable) -> {
                if(Objects.nonNull(throwable)){
                    throwable.printStackTrace();
                    logger.info("接口推送OMS订单消息发送失败：{}", throwable.getMessage());
                    KafkaSendErrorRecord errorRecord = new KafkaSendErrorRecord();
                    errorRecord.setDataText(JSONObject.toJSONString(vo));
                    errorRecord.setQueueName(KafkaConstants.HWG_TOPIC_ORDER_QUEUE);
                    errorRecord.setRemark(throwable.getMessage());
                    errorRecord.setUuid(vo.getUuid());
                    kafkaSendErrorRecordService.checkAndSave(errorRecord);
                }
            });
        }
        return Result.success();
    }


    @Operation(summary = "OMS订单或者售后单导入", security = {@SecurityRequirement(name = "Authorization")})
    @PostMapping("/_import/{storeCode}/{omsReturnOrder}")
    public Result<?> importData(@Parameter(description = "店铺CODE") @PathVariable String storeCode, @Parameter(description = "是否是OMS售后单") @PathVariable Integer omsReturnOrder, @Parameter(description = "文件") @RequestParam("file") MultipartFile file) {
        boolean isOmsReturnOrder = omsReturnOrder == 1;
        List<Map<String, String>> list = EasyExcelImportUtils.makeData(file, null, 0, 1);
        if (list.size() == 0) {
            return Result.success();
        }
        // 检查标题是否有【平台唯一ID】字段
        if (list.get(0).keySet().stream().noneMatch(item -> Objects.equals(item, SystemConstants.PLATFORM_UNIQUE_FLAG))) {
            return Result.failed("标题缺少【%s】，请添加后再导入".formatted(SystemConstants.PLATFORM_UNIQUE_FLAG));
        }
        // 检查平台唯一ID是否为空
        if (list.stream().anyMatch(item -> Objects.nonNull(item) && !StringUtils.hasText(item.get(SystemConstants.PLATFORM_UNIQUE_FLAG)))) {
            return Result.failed("【%s】字段不能为空，请添加后再导入".formatted(SystemConstants.PLATFORM_UNIQUE_FLAG));
        }
        LocalDateTime time;
        List<SysBaseColumnMatch> configListByPlatform;
        List<SysBaseColumnMatch> allConfigListByPlatform;
        if (isOmsReturnOrder) {
            configListByPlatform = sysBaseColumnMatchService.getBusinessConfigListByPlatform(SystemConstants.OMS_RETURN_ORDER_DICT_KEY, null);
            // 配置的账单月份
            if (configListByPlatform.size() == 0) {
                return Result.failed("售后单没有配置到【业务日期】对应关系，导入失败");
            }
            allConfigListByPlatform = sysBaseColumnMatchService.getByPlatform(SystemConstants.OMS_RETURN_ORDER_DICT_KEY);
            // 判断是否有唯一标识的配置
            if (allConfigListByPlatform.stream().noneMatch(item -> Objects.equals(item.getSourceColumn(), SystemConstants.PLATFORM_UNIQUE_FLAG))) {
                return Result.failed("售后单没有配置到【唯一标识】对应关系，导入失败");
            }
        } else {
            configListByPlatform = sysBaseColumnMatchService.getBusinessConfigListByPlatform(SystemConstants.OMS_ORDER_DICT_KEY, null);
            // 配置的账单月份
            if (configListByPlatform.size() == 0) {
                return Result.failed("OMS订单没有配置到【业务日期】对应关系，导入失败");
            }
            allConfigListByPlatform = sysBaseColumnMatchService.getByPlatform(SystemConstants.OMS_ORDER_DICT_KEY);
            // 判断是否有唯一标识的配置
            if (allConfigListByPlatform.stream().noneMatch(item -> Objects.equals(item.getSourceColumn(), SystemConstants.PLATFORM_UNIQUE_FLAG))) {
                return Result.failed("OMS订单没有配置到【唯一标识】对应关系，导入失败");
            }
        }
        String sourceColumn = configListByPlatform.get(0).getSourceColumn();
        for (Map<String, String> stringStringMap : list) {
            // 订单
            if (StringUtils.hasText(stringStringMap.get(sourceColumn))) {
                time = DateUtils.convertStringToLocalDateTime(stringStringMap.get(sourceColumn));
                if (Objects.isNull(time)) {
                    return Result.failed("第" + (list.indexOf(stringStringMap) + 1) + "行数据，【业务日期】对应的字段【%s】值【%s】日期格式错误".formatted(sourceColumn, stringStringMap.get(sourceColumn)));
                }
            } else {
                return Result.failed("第" + (list.indexOf(stringStringMap) + 1) + "行数据，【业务日期】对应的字段【%s】值不能为空".formatted(sourceColumn));
            }
        }
        Map<String, String> dataMap;
        SysStore store = sysStoreService.getByCode(storeCode);
        // 获取第一行标题
        Set<String> importExcelHeadList = list.get(0).keySet();
        // OMS退货单字段对应关系
        Map<String, String> omsReturnOrderColumn = OriginalOmsReturnOrderImportVo.getKeyMap();
        // OMS销售订单字段对应关系
        Map<String, String> omsOrderColumn = OriginalOmsOrderImportVo.getMainKeyMap();
        boolean hasColumn;
        if (isOmsReturnOrder) {
            // 比较标题是否一样
            for (String columnCn : omsReturnOrderColumn.keySet()) {
                hasColumn = importExcelHeadList.stream().anyMatch(s -> Objects.equals(s, columnCn));
                Assert.isTrue(hasColumn, "导入表格缺少列【%s】，请添加【%s】再导入".formatted(columnCn, columnCn));
            }
            // 过滤空行 关联订单号、退单交易号、原始交易号都为空
            list = list.stream().filter(item -> Objects.nonNull(item.get("关联订单号")) && StringUtils.hasText(item.get("关联订单号")) &&
                    Objects.nonNull(item.get("退单交易号")) && StringUtils.hasText(item.get("退单交易号")) &&
                    Objects.nonNull(item.get("原始交易号")) && StringUtils.hasText(item.get("原始交易号"))).toList();
        } else {
            for (String columnCn : omsOrderColumn.keySet()) {
                hasColumn = importExcelHeadList.stream().anyMatch(s -> Objects.equals(s, columnCn));
                Assert.isTrue(hasColumn, "导入表格缺少列【%s】，请添加【%s】再导入".formatted(columnCn, columnCn));
            }
            // 过滤空行 OMS单号、网店交易号、子交易号都为空
            list = list.stream().filter(item -> Objects.nonNull(item.get("OMS单号")) && StringUtils.hasText(item.get("OMS单号")) &&
                    Objects.nonNull(item.get("网店交易号")) && StringUtils.hasText(item.get("网店交易号")) &&
                    Objects.nonNull(item.get("子交易号")) && StringUtils.hasText(item.get("子交易号"))).toList();
        }
        for (Map<String, String> data : list) {
            dataMap = new HashMap<>();
            MessageVo vo = new MessageVo();
            // 是否是OMS售后单
            vo.setOmsReturnOrder(isOmsReturnOrder);
            // 是否是OMS订单
            vo.setOmsOrder(true);
            // 转换ID成英文
            dataMap.put("pId", data.get(SystemConstants.PLATFORM_UNIQUE_FLAG));
            // 店铺
            vo.setStoreId(store.getId());
            String value;
            if (isOmsReturnOrder) {
                // OMS售后单
                for (String key : omsReturnOrderColumn.keySet()) {
                    value = data.get(key);
                    if (Objects.isNull(value)) {
                        value = "";
                    } else {
                        value = value.replace("_x000D_", "").strip();
                    }
                    dataMap.put(omsReturnOrderColumn.get(key), value);
                }
            } else {
                // OMS销售订单
                for (String key : OriginalOmsOrderImportVo.getKeyMap().keySet()) {
                    value = data.get(key);
                    if (Objects.isNull(value)) {
                        value = "";
                    } else {
                        value = value.replace("_x000D_", "").strip();
                    }
                    dataMap.put(OriginalOmsOrderImportVo.getKeyMap().get(key), value);
                }
            }
            vo.setDataMap(dataMap);
            // 推送到转换标准订单的消息队列
            vo.setUuid(snowflakeIdWorker.nextId());
            CompletableFuture<SendResult<String, String>> completableFuture = kafkaTemplate.send(KafkaConstants.HWG_TOPIC_ORDER_QUEUE, JSONObject.toJSONString(vo));
            completableFuture.whenComplete((result, ex) -> {
                if (Objects.nonNull(ex)) {
                    ex.printStackTrace();
                    logger.info("推送OMS订单数据到消息队列失败，失败原因：{}", ex.getMessage());
                    KafkaSendErrorRecord errorRecord = new KafkaSendErrorRecord();
                    errorRecord.setDataText(JSONObject.toJSONString(vo));
                    errorRecord.setQueueName(KafkaConstants.HWG_TOPIC_ORDER_QUEUE);
                    errorRecord.setRemark(ex.getMessage());
                    errorRecord.setUuid(vo.getUuid());
                    kafkaSendErrorRecordService.checkAndSave(errorRecord);
                }
            });
        }
        return Result.success();
    }
}
